`timescale 1ns/1ns
module dual_port_RAM #(parameter DEPTH = 16,
                       parameter WIDTH = 8)(
           input wclk
           , input wenc
           , input [$clog2(DEPTH) - 1: 0] waddr  //深度对2取对数，得到地址的位宽。
           , input [WIDTH - 1: 0] wdata      //数据写入
           , input rclk
           , input renc
           , input [$clog2(DEPTH) - 1: 0] raddr  //深度对2取对数，得到地址的位宽。
           , output reg [WIDTH - 1: 0] rdata //数据输出
       );

reg [WIDTH - 1: 0] RAM_MEM [0: DEPTH - 1];

always @(posedge wclk)
	begin
		if (wenc)
			RAM_MEM[waddr] <= wdata;
	end

always @(posedge rclk)
	begin
		if (renc)
			rdata <= RAM_MEM[raddr];
	end

endmodule


    module sfifo#(
        parameter WIDTH = 8,
        parameter DEPTH = 16
    )(
        input clk	,
        input rst_n	,
        // input wrstn	,
        // input	rrstn	,
        input winc	,
        input rinc	,
        input [WIDTH - 1: 0]	wdata	,

        output reg	wfull	,
        output reg	rempty	,
        output wire [WIDTH - 1: 0]	rdata
    );

parameter ADDR_WIDTH = $clog2(DEPTH);

reg [ADDR_WIDTH: 0] waddr;
reg [ADDR_WIDTH: 0] raddr;

always@(posedge clk or negedge rst_n)
	begin
		if (!rst_n)
			waddr <= 'd0;
		else if (winc & !wfull)
			waddr <= waddr + 'd1;
	end

always@(posedge clk or negedge rst_n)
	begin
		if (!rst_n)
			raddr <= 'd0;
		else if (rinc & !rempty)
			raddr <= raddr + 'd1;
	end

wire [ADDR_WIDTH: 0] fifo_cnt;

assign fifo_cnt = (waddr[ADDR_WIDTH] == raddr[ADDR_WIDTH]) ? (waddr[ADDR_WIDTH : 0] - raddr[ADDR_WIDTH : 0]) :
       (DEPTH + waddr[ADDR_WIDTH - 1 : 0] - raddr[ADDR_WIDTH - 1 : 0]);


always@(posedge clk or negedge rst_n)
	begin
		if (~rst_n)
			begin
				wfull <= 'd0;
				rempty <= 'd0;
			end
		else if (fifo_cnt == 'd0)
			begin
				rempty <= 1'd1;
			end
		else if (fifo_cnt == DEPTH)
			begin
				wfull <= 1'd1;
			end
		else
			begin
				wfull <= 'd0;
				rempty <= 'd0;
			end
	end

wire wen;
wire ren;
// wire wren;
assign wen = winc & !wfull;
assign ren = rinc & !rempty;


dual_port_RAM #(.DEPTH(DEPTH),
                .WIDTH(WIDTH)
               )dual_port_RAM(
                  .wclk (clk),
                  .wenc (wen),
                  .waddr(waddr[ADDR_WIDTH - 1: 0]),   //深度对2取对数，得到地址的位宽。
                  .wdata(wdata),            //数据写入
                  .rclk (clk),
                  .renc (ren),
                  .raddr(raddr[ADDR_WIDTH - 1: 0]),    //深度对2取对数，得到地址的位宽。
                  .rdata(rdata)         //数据输出
              );

endmodule

